﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ApprovalFlow.Interface;

namespace ApprovalFlow.Models
{
    public abstract class WorkflowStep
    {
        public abstract Type BodyType { get; }

        /// <summary>
        /// 执行初始化
        /// </summary>
        /// <param name="workflow"></param>
        /// <param name="executionPointer"></param>
        /// <returns></returns>
        public virtual ExecutionPipelineDirective InitForExecution(WorkflowInstance workflow, ExecutionPointer executionPointer)
        {
            return ExecutionPipelineDirective.Next;
        }

        /// <summary>
        /// 执行前
        /// </summary>
        /// <param name="context"></param>
        /// <param name="executionPointer"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public virtual ExecutionPipelineDirective BeforeExecute(IStepExecutionContext context, ExecutionPointer executionPointer, IStepBody body)
        {
            return ExecutionPipelineDirective.Next;
        }

        /// <summary>
        /// 执行后
        /// </summary>
        /// <param name="context"></param>
        /// <param name="stepResult"></param>
        /// <param name="executionPointer"></param>
        public virtual void AfterExecute(IStepExecutionContext context, ExecutionResult stepResult, ExecutionPointer executionPointer)
        {
        }

        public virtual IStepBody ConstructBody(IServiceProvider serviceProvider)
        {
            IStepBody body = (serviceProvider.GetService(BodyType) as IStepBody);
            if (body == null)
            {
                var stepCtor = BodyType.GetConstructor(Array.Empty<Type>());
                if (stepCtor != null)
                    body = (stepCtor.Invoke(null) as IStepBody);
            }
            return body;
        }
    }

    public class WorkflowStep<TStepBody> : WorkflowStep where TStepBody : IStepBody
    {
        public override Type BodyType => typeof(TStepBody);
    }
}
